package com.kly.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.toolkit.Db;
import com.kly.constants.UserConstant;
import com.kly.domain.dto.space.SpaceAddRequest;
import com.kly.domain.dto.space.SpaceQueryRequest;
import com.kly.domain.entity.Space;
import com.kly.domain.entity.SpaceUser;
import com.kly.domain.entity.User;
import com.kly.domain.enums.SpaceLevelEnum;
import com.kly.domain.enums.SpaceRoleEnum;
import com.kly.domain.enums.SpaceTypeEnum;
import com.kly.domain.vo.UserVO;
import com.kly.domain.vo.space.SpaceVO;
import com.kly.exception.BusinessException;
import com.kly.exception.ErrorCode;
import com.kly.exception.ThrowUtils;
import com.kly.mapper.SpaceMapper;
import com.kly.service.SpaceService;
import com.kly.service.UserService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author admin
 * @description 针对表【space(空间)】的数据库操作Service实现
 * @createDate 2025-03-11 12:40:49
 */
@Service
@RequiredArgsConstructor
public class SpaceServiceImpl extends ServiceImpl<SpaceMapper, Space>
        implements SpaceService {

    private final UserService userService;

    private final TransactionTemplate transactionTemplate;

    // @Lazy
    // @Resource
    // private DynamicShardingManager dynamicShardingManager;



    @Override
    public QueryWrapper<Space> getQueryWrapper(SpaceQueryRequest spaceQueryRequest) {
        if (spaceQueryRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "请求参数为空");
        }
        Long id = spaceQueryRequest.getId();
        String spaceName = spaceQueryRequest.getSpaceName();
        Integer spaceLevel = spaceQueryRequest.getSpaceLevel();
        Long userId = spaceQueryRequest.getUserId();
        String sortField = spaceQueryRequest.getSortField();
        String sortOrder = spaceQueryRequest.getSortOrder();
        Integer spaceType = spaceQueryRequest.getSpaceType();
        SpaceTypeEnum spaceTypeEnum = SpaceTypeEnum.getEnumByLevel(spaceType);

        QueryWrapper<Space> queryWrapper = new QueryWrapper<>();

        queryWrapper.eq(ObjUtil.isNotNull(id), "id", id);
        queryWrapper.like(StrUtil.isNotBlank(spaceName), "space_name", spaceName);
        queryWrapper.eq(ObjUtil.isNotNull(spaceLevel), "space_level", spaceLevel);
        queryWrapper.like(ObjUtil.isNotNull(userId), "user_id", userId);
        // 空间类型
        queryWrapper.eq(ObjUtil.isNotNull(spaceTypeEnum), "space_type", spaceType);

        queryWrapper.orderBy(StrUtil.isNotBlank(sortField), sortOrder.equals("ascend"), sortField);


        return queryWrapper;
    }

    @Override
    public SpaceVO getSpaceVO(Space space, HttpServletRequest request) {
        ThrowUtils.throwIf(space == null, ErrorCode.PARAMS_ERROR, "图片不存在");
        SpaceVO spaceVO = SpaceVO.objToVo(space);
        Long userId = space.getUserId();
        if (userId != null && userId > 0) {
            User userDb = userService.getById(userId);
            UserVO userVo = userService.getUserVo(userDb);
            spaceVO.setUser(userVo);
        }
        return spaceVO;
    }

    @Override
    public void validateSpaceInfo(Space space) {
        ThrowUtils.throwIf(space == null, ErrorCode.PARAMS_ERROR, "参数为空");
        String spaceName = space.getSpaceName();
        Integer spaceLevel = space.getSpaceLevel();
        ThrowUtils.throwIf(StrUtil.isBlank(spaceName) || spaceName.length() > 30, ErrorCode.PARAMS_ERROR, "空间名不能为空");
        ThrowUtils.throwIf(SpaceLevelEnum.getEnumByLevel(spaceLevel) == null, ErrorCode.PARAMS_ERROR, "空间等级错误");
        ThrowUtils.throwIf(SpaceTypeEnum.getEnumByLevel(space.getSpaceType()) == null, ErrorCode.PARAMS_ERROR, "空间类型错误");
    }

    @Override
    public Page<SpaceVO> listSpaceVOByPage(Page<Space> page) {
        List<Space> records = page.getRecords();
        Page<SpaceVO> spaceVOPage = new Page<>();
        if (CollUtil.isEmpty(records)) {
            return spaceVOPage;
        }
        List<SpaceVO> spaceVOList = records.stream().map(SpaceVO::objToVo).collect(Collectors.toList());
        Set<Long> userIdList = spaceVOList.stream().map(SpaceVO::getUserId).collect(Collectors.toSet());

        Map<Long, List<User>> idUserMap = userService.listByIds(userIdList).stream().collect(Collectors.groupingBy(User::getId));
        spaceVOList.forEach(spaceVO -> {
            Long userId = spaceVO.getUserId();
            if (idUserMap.containsKey(userId)) {
                List<User> userList = idUserMap.get(userId);
                User user = userList.get(0);
                UserVO userVO = userService.getUserVo(user);
                spaceVO.setUser(userVO);
            }
        });
        spaceVOPage.setRecords(spaceVOList);
        spaceVOPage.setTotal(page.getTotal());
        return spaceVOPage;
    }

    @Override
    public void fillSpaceInfo(Space space) {
        Integer spaceLevel = space.getSpaceLevel();
        SpaceLevelEnum spaceLevelEnum = SpaceLevelEnum.getEnumByLevel(spaceLevel);
        ThrowUtils.throwIf(spaceLevelEnum == null, ErrorCode.PARAMS_ERROR, "空间等级错误");

        if (space.getMaxCount() == null) {
            space.setMaxCount(spaceLevelEnum.getMaxCount());
        }

        if (space.getMaxSize() == null) {
            space.setMaxSize(spaceLevelEnum.getMaxSize());
        }
    }

    @Override
    public Long addSpace(SpaceAddRequest spaceAddRequest, User loginUser) {
        ThrowUtils.throwIf(spaceAddRequest == null, ErrorCode.PARAMS_ERROR, "参数为空");
        // 1. 校验参数 校验合法
        Space space = BeanUtil.copyProperties(spaceAddRequest, Space.class);
        Long userId = loginUser.getId();
        space.setUserId(userId);
        // 2. 校验权限
        if (!SpaceLevelEnum.COMMON.equals(SpaceLevelEnum.getEnumByLevel(space.getSpaceLevel())) && !UserConstant.ADMIN_ROLE.equals(loginUser.getUserRole())) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "没有权限");
        }
        // 获取space type 设置默认值
        Integer spaceType = Optional.ofNullable(spaceAddRequest.getSpaceType()).orElse(SpaceTypeEnum.PRIVATE.getType());
        Integer spaceLevel = Optional.ofNullable(spaceAddRequest.getSpaceLevel()).orElse(SpaceLevelEnum.COMMON.getLevel());
        space.setSpaceType(spaceType);
        space.setSpaceLevel(spaceLevel);
        // 3. 互斥锁 添加空间
        synchronized (userId.toString().intern()) {
            return transactionTemplate.execute(status -> {
                // 4. 判断用户是否添加普通空间
                boolean exists = this.lambdaQuery()
                        .eq(Space::getUserId, userId)
                        .eq(Space::getSpaceType, spaceType)
                        .exists();
                ThrowUtils.throwIf(exists, ErrorCode.OPERATION_ERROR, "不能添加多个空间");
                // 填充默认值
                fillSpaceInfo(space);
                boolean save = this.save(space);
                ThrowUtils.throwIf(!save, ErrorCode.OPERATION_ERROR, "添加失败");

                // 判断如果是团队空间， 关联用户和空间
                if(SpaceTypeEnum.TEAMED.equals(SpaceTypeEnum.getEnumByLevel(space.getSpaceType()))) {
                    SpaceUser spaceUser = new SpaceUser();
                    spaceUser.setSpaceId(space.getId());
                    spaceUser.setUserId(userId);
                    spaceUser.setSpaceRole(SpaceRoleEnum.ADMIN.getValue());
                    boolean flag = Db.save(spaceUser);
                    ThrowUtils.throwIf(!flag, ErrorCode.OPERATION_ERROR, "添加失败");
                }
                // 创建分表
                // dynamicShardingManager.createSpacePictureTable(space);
                return space.getId();
            });
        }
    }

}




